package com.teamin.service.impl;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.google.common.collect.Lists;
import com.mysql.cj.core.util.StringUtils;
import com.teamin.config.ErrorCode;
import com.teamin.config.TeaminProperties;
import com.teamin.dto.NetDiskShareDTO;
import com.teamin.entity.NetDisk;
import com.teamin.entity.NetDiskShare;
import com.teamin.entity.NetDiskShareFile;
import com.teamin.mapper.NetDiskMapper;
import com.teamin.service.*;
import com.teamin.utils.HttpKit;
import com.teamin.vo.FileFromVO;
import com.teamin.vo.NetDiskFoldersByParentIdVO;
import com.teamin.web.Evn;
import com.teamin.web.common.exception.DataException;
import com.teamin.web.common.exception.FileNotExistException;
import com.teamin.web.common.exception.NotBelongCircleException;
import com.teamin.web.exception.GlobalErrorInfoException;
import com.teamin.web.model.ErrorInfo;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 网盘服务接口实现类
 * <p>
 * Created by e on 2017/11/20
 *
 * @author <a href="http://eregg.com">eregg</a>
 */
@Service
public class NetDiskServiceImpl implements INetDiskService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    NetDiskMapper netDiskMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private WebsocketService websocketService;

    @Autowired
    private TeaminProperties teaminProperties;

    @Autowired
    private LogServiceImpl logService;

    @Autowired
    private TaskService taskService;

    @Override
    public boolean save(NetDisk netDisk) {
        boolean res = netDiskMapper.save(netDisk) > 0;

        if(netDisk.getIsdelete() != null && netDisk.getIsdelete() == 0){
            try {
                //圈子成功 发送通知
                HttpServletRequest request = HttpKit.getRequest();
                Long controlUser = Long.valueOf(request.getAttribute("loginUserId").toString());
                String userFlag = request.getAttribute("userFlag").toString();
                Long circleId = Long.valueOf(request.getParameter("circleId"));

                List<NetDisk> netDisks = Lists.newArrayList(netDisk);

                //发送socket通知
                websocketService.sendCircle(controlUser, circleId, WebsocketService.CirclePropertise.NET_DISK_FILE_MODIFY, WebsocketService.Control.ADD, netDisks, userFlag);

            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.toString());
            }
        }

        return res;
    }


    @Override
    public List<NetDisk> listFilesByAnnex(Integer circleId) {

        return netDiskMapper.listFilesByAnnex(circleId);
    }

    @Override
    public List<NetDisk> findFiles(NetDisk netDisk) {

        List<NetDisk> netDisks = Lists.newArrayList();

        if (netDisk.getId() == null || netDisk.getId() == 0) {
            netDisks = this.netDiskMapper.findFiles(netDisk);
        } else {
            findr(netDisk, netDisks);
        }

        return netDisks;
    }

    @Override
    public List<NetDisk> findChild(NetDisk netDisk) {
        return this.netDiskMapper.findChild(netDisk);
    }

    /**
     * @Author: yangrui
     * @Description: 重命名文件/文件夹
     * @Date: 下午2:57 2017/11/28
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean rename(Long loginUserId, NetDisk netDisk)throws GlobalErrorInfoException {

        HttpServletRequest request = HttpKit.getRequest();
        Long circleId = Long.valueOf(request.getParameter("circleId"));

        // 文件夹名称存在
        Long id = netDiskMapper.fileNameExist(Integer.valueOf(circleId.toString()), netDisk.getFileName(), Integer.valueOf(netDisk.getParentId().toString()));

        if (id != null) {
            throw new GlobalErrorInfoException(new ErrorInfo(HttpStatus.INTERNAL_SERVER_ERROR, ErrorCode.FILE_NAME_EXIST));
        }

        FileFromVO fileFromVO = netDiskMapper.findFileFrom(netDisk.getId());
        int i = 0;
        if (fileFromVO != null) {
            /*if (!fileFromVO.getUserId().equals(loginUserId) && fileFromVO.getParentId() == -1) {
                throw new UnauthorizedException();
            }*/
            String oldFileName = fileFromVO.getFileName();
            netDisk.setUpdateUserid(loginUserId);
            i = netDiskMapper.rename(netDisk);
            if (i > 0) {
                if (fileFromVO.getParentId() == -1) {
                    if (fileFromVO.getTaskId() != null) {
                        logService.insertTaskLog(Long.valueOf(fileFromVO.getTaskId()), LogService.HANDLE.MODIFY, LogService.TaskHandleField.TASK_FILE_NAME, fileFromVO.getUserId(), StringUtils.isNullOrEmpty(fileFromVO.getNickName()) == true ? fileFromVO.getUserName() : fileFromVO.getNickName(), netDisk.getFileName(), oldFileName);
                    }
                }

                try {

                    Long controlUser = Long.valueOf(request.getAttribute("loginUserId").toString());
                    String userFlag = request.getAttribute("userFlag").toString();

                    netDisk = netDiskMapper.findById(netDisk.getId());

                    //发送socket通知
                    websocketService.sendCircle(controlUser, circleId, WebsocketService.CirclePropertise.NET_DISK_FILE_MODIFY, WebsocketService.Control.MODIFY, netDisk, userFlag);

                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error(e.toString());
                }

            }
        }
        return i > 0;
    }

    @Override
    public NetDisk fileDetails(Long id) {
        NetDisk netDisk = netDiskMapper.fileDetails(id);
        if (StringUtils.isNullOrEmpty(netDisk.getCreateUserName())) {
            if (!StringUtils.isNullOrEmpty(netDisk.getUserName())) {
                netDisk.setCreateUserName(netDisk.getUserName());
            }
        }
        return netDisk;
    }

    @Override
    public NetDisk folderDetails(Long id) {
        NetDisk netDisk = netDiskMapper.folderDetails(id);
        if (StringUtils.isNullOrEmpty(netDisk.getCreateUserName())) {
            if (!StringUtils.isNullOrEmpty(netDisk.getUserName())) {
                netDisk.setCreateUserName(netDisk.getUserName());
            }
        }
        if (StringUtils.isNullOrEmpty(netDisk.getUpdateUserName())) {
            if (!StringUtils.isNullOrEmpty(netDisk.getUserUpdateName())) {
                netDisk.setUpdateUserName(netDisk.getUserUpdateName());
            }
        }

        try{
            /**获取目录大小（包含子目录中的文件）**/
            //获取所有子目录，子文件
            List<NetDisk> netDisks = Lists.newArrayList();
            findr(netDisk, netDisks);
            //所有自文件大小相加
            Long totalSize = 0L;
            for(NetDisk n : netDisks){
                if(n.getIsFile() == 1){
                    totalSize = totalSize+n.getFileSize();
                }
            }
            netDisk.setTotalSize(totalSize);
            /**获取目录大小（包含子目录中的文件） end**/

        }catch (Exception e){
            e.printStackTrace();
            logger.error(e.getMessage());
        }


        return netDisk;
    }

    @Override
    public NetDiskShare createShare(NetDiskShareDTO netDiskShareDTO) {
        /*判断文件是否存在*/
        String[] arr = netDiskShareDTO.getFileIds().split(",");
        List<Long> list = new ArrayList<>();
        for (String str : arr) {
            list.add(Long.valueOf(str));
        }
        Long l = netDiskMapper.fileExist(netDiskShareDTO.getCircleId(), list);
        if (netDiskShareDTO.getFileIds().split(",").length != l) {
            throw new FileNotExistException();
        }

        NetDiskShare netDiskShare = new NetDiskShare();
        netDiskShare.setShareUserId(netDiskShareDTO.getCreateUserId());
        this.netDiskMapper.createShare(netDiskShare);

        Long shareId = netDiskShare.getId();

        for (String fileId : netDiskShareDTO.getFileIds().split(",")) {
            NetDiskShareFile netDiskShareFile = new NetDiskShareFile();
            netDiskShareFile.setShareId(shareId);
            netDiskShareFile.setFileId(Long.valueOf(fileId));
            this.netDiskMapper.insertShareFile(netDiskShareFile);
        }

        return netDiskShare;
    }

    @Override
    public List<NetDisk> findByShare(Long shareId) {
        return this.netDiskMapper.findByShare(shareId);
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Override
    public Integer rm(Long loginUserId, List<String> ids) {

        List<NetDisk> netDisks = new ArrayList<>();
        for (String id : ids) {
            NetDisk netDisk = this.netDiskMapper.findById(Long.valueOf(id));
            if (netDisk != null) {
                netDisks.add(netDisk);
            }
            /*只有创建人可以操作来自任务附近的文件*/
            /*if (!netDisk.getCreateUserid().equals(loginUserId) && netDisk.getParentId() == -1) {
                throw new UnauthorizedException();
            }*/
            FileFromVO fileFromVO = netDiskMapper.findFileFrom(Long.valueOf(id));
            if (fileFromVO != null) {
                if (fileFromVO.getParentId() == -1 && fileFromVO.getIsFile() == 1) {
                    logService.insertTaskLog(Long.valueOf(fileFromVO.getTaskId()), LogService.HANDLE.DELETE, LogService.TaskHandleField.TASK_FILE, fileFromVO.getUserId(), StringUtils.isNullOrEmpty(fileFromVO.getNickName()) == true ? fileFromVO.getUserName() : fileFromVO.getNickName(), fileFromVO.getFileName());
                }
            }
            /*根据文件ID查询commentId，同步删除tb_file文件*/
            /*Integer commentId = netDiskMapper.findCommentId(Long.valueOf(id));
            if (commentId != null) {
                try {
                    taskService.deleteCommentById(Long.valueOf(commentId));
                } catch (GlobalErrorInfoException e) {
                    e.printStackTrace();
                }
            }*/
        }
        Integer res = rmr(netDisks);
        if (res > 0) {

            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

                Long controlUser = Long.valueOf(request.getAttribute("loginUserId").toString());
                String userFlag = request.getAttribute("userFlag").toString();
                Long circleId = Long.valueOf(request.getParameter("circleId"));


                //发送socket通知
                websocketService.sendCircle(controlUser, circleId, WebsocketService.CirclePropertise.NET_DISK_FILE_MODIFY, WebsocketService.Control.DELETE, netDisks, userFlag);

            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.toString());
            }
        }

        return res;
    }

    /**
     * @Author: yangrui
     * @Description: 根据节点显示文件夹列表
     * @Date: 下午3:06 2017/11/24
     */
    @Override
    public List<NetDiskFoldersByParentIdVO> foldersByParentId(Long loginUserId, Integer circleId, Long parentId) {
        // 不属于圈子
        if (!userService.userInCircle(loginUserId, Long.valueOf(circleId))) {
            throw new NotBelongCircleException();
        }
        /*判断该圈子下是否存在该结点*/
        /*Long l = netDiskMapper.existByParentId(circleId, parentId);
        if (0 == l) {
            throw new FileNotExistException();
        }*/
        return netDiskMapper.foldersByParentId(circleId, parentId);
    }

    /**
     * @Author: yangrui
     * @Description: 文件移动至
     * @Date: 下午4:11 2017/11/24
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void fileMove(Long loginUserId, Integer circleId, String fileIds, Long parentId) {
        // 不属于圈子
        if (!userService.userInCircle(loginUserId, Long.valueOf(circleId))) {
            throw new NotBelongCircleException();
        }
        /*如果不移动至根目录，需判断圈子是否存在parentId*/
        if (parentId != 0) {
            Long l = netDiskMapper.exist(Integer.valueOf(parentId + ""), circleId);
            if (l == null) {
                throw new FileNotExistException();
            }
        }
        /*判断文件/文件夹是否存在*/
        String[] fieldArr = fileIds.split(",");
        List<Long> list = new ArrayList<>();
        for (String str : fieldArr) {
            list.add(Long.valueOf(str));
        }
        Long l = netDiskMapper.fileExist(circleId, list);
        if (fieldArr.length != l) {
            throw new FileNotExistException();
        }
        for (Long id : list) {
            /*id parentId 不能一样*/
            if (id.equals(parentId)) {
                throw new DataException();
            }
            /*NetDisk netDisk = netDiskMapper.findById(id);
            if (!netDisk.getCreateUserid().equals(loginUserId) && netDisk.getParentId() == -1) {
                throw new UnauthorizedException();
            }*/
            netDiskMapper.fileMove(loginUserId, parentId, id);

        }

        try {

            HttpServletRequest request = HttpKit.getRequest();
            Long controlUser = Long.valueOf(request.getAttribute("loginUserId").toString());
            String userFlag = request.getAttribute("userFlag").toString();
            List<NetDisk> netDisks = Lists.newArrayList();
            for (Long id : list) {
                NetDisk netDisk = netDiskMapper.findById(id);
                netDisks.add(netDisk);

            }


            //发送socket通知
            websocketService.sendCircle(controlUser, Long.valueOf(circleId), WebsocketService.CirclePropertise.NET_DISK_FILE_MOVE, WebsocketService.Control.MOVE, netDisks, userFlag);

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }
    }

    @Override
    public void rmOSSFile() {
        List<NetDisk> netDiskMapperDeleted = this.netDiskMapper.findDeleted(teaminProperties.getNetDisk().getRmRule());
        Map<String, Long> map = new HashMap<>();
        List<String> uuidList = new ArrayList<>();
        for (NetDisk netDisk : netDiskMapperDeleted) {
            uuidList.add(netDisk.getUuid());
        }

        if (uuidList.size() != 0) {
            OSSClient client = new OSSClient(Evn.ALIYUN_OSS_ENDPOINT, Evn.ALIYUN_OSS_KEYID, Evn.ALIYUM_OSS_KEYSECRET);
            DeleteObjectsResult deleteObjectsResult = client.deleteObjects(new DeleteObjectsRequest(Evn.ALIYUN_OSS_BUCKENAME).withKeys(uuidList));

            List<String> obs = deleteObjectsResult.getDeletedObjects();

            logger.info("rm oss result:{}", JSONObject.fromObject(obs));
        }
    }

    @Override
    public NetDisk getByUUID(String uuid) {
        return this.netDiskMapper.getByUUID(uuid);
    }

    @Override
    public void uploadSuccessHandler(List<String> uuidList) {

        //更新 文件为有效状态
        Integer res = this.netDiskMapper.enabled(uuidList);

        try {
            //圈子成功 发送通知
            HttpServletRequest request = HttpKit.getRequest();
            Long controlUser = Long.valueOf(request.getAttribute("loginUserId").toString());
            String userFlag = request.getAttribute("userFlag").toString();
            Long circleId = Long.valueOf(request.getParameter("circleId"));

            List<NetDisk> netDisks = this.netDiskMapper.listByUUidList(uuidList);

            //发送socket通知
            websocketService.sendCircle(controlUser, circleId, WebsocketService.CirclePropertise.NET_DISK_FILE_MODIFY, WebsocketService.Control.ADD, netDisks, userFlag);

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }

    }


    /**
     * 递归删除文件目录
     *
     * @param netDisks
     * @return
     */
    private Integer rmr(List<NetDisk> netDisks) {
        List<Long> ids = new ArrayList<>();
        for (NetDisk netDiskFile : netDisks) {
            ids.add(netDiskFile.getId());
            if (netDiskFile.getIsFile() == 0) {
                rmr(this.netDiskMapper.findChild(netDiskFile));
            }
        }
        if (ids.size() > 0) {
            return this.netDiskMapper.rm(ids);
        }
        return 0;
    }

    /**
     * 递归查询文件目录
     *
     * @param netDisks
     * @return
     */
    private void findr(NetDisk netDisk, List<NetDisk> netDisks) {

        List<NetDisk> diskList = this.findChild(netDisk);

        for (NetDisk netDiskFile : diskList) {
            netDisks.add(netDiskFile);
            if (netDiskFile.getIsFile() == 0) {
                NetDisk netDisk1 = new NetDisk();
                BeanUtils.copyProperties(netDiskFile, netDisk1);
                netDisk1.setFileName(netDisk.getFileName());
                findr(netDisk1, netDisks);
            }
        }
    }

}
